home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / rules / stubs / stubrel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  16.2 KB  |  648 lines

  1. /*===================================================================
  2.  *
  3.  * FILE:
  4.  * stubrel.c
  5.  *
  6.  * IDENTIFICATION:
  7.  * $Header: /private/postgres/src/rules/stubs/RCS/stubrel.c,v 1.16 1992/03/25 17:31:27 hong Exp $
  8.  *
  9.  *
  10.  * DESCRIPTION:
  11.  * These routines access the system relation "pg_prs2stub.h" where
  12.  * the ruls stubs for the various relations are stored.
  13.  * Each relation can have zero or more stubs, and unfortunately
  14.  * if it has more "more" than "zero" we end up with a total stub
  15.  * size greater than 8K. And as tuples can NOT be longer than 8K,
  16.  * and big objects are not implemented yet, we have to break up the
  17.  * stubs in smaller pieces, each one stores in a separate tuple.
  18.  *
  19.  * The pg_prs2stub relation has the following fields:
  20.  *    prs2relid:    the oid of the relation
  21.  *    prs2islast:    true if this is the last piece of stub
  22.  *            we have to look for...
  23.  *     prs2no:        the number of the stub piece stored in this
  24.  *            tuple (we start countiong from 0).
  25.  *    prs2stub:    the stub (or a small piece of it..)
  26.  *
  27.  * for example, if the relation with oid 1234 has its stub stored
  28.  * in 3 pieces, then pg_prs2stub will contain the following 3 tuples:
  29.  *
  30.  *   prs2relid   prs2islast  prs2no    prs2stub
  31.  *   ---------   ----------  ------     ---------
  32.  *    1234        f    0    < 1st piece >
  33.  *    1234        f    1    < 2nd piece >
  34.  *    1234        t    2    < 3rd piece >
  35.  *
  36.  * The 'prs2stub' field is of type "stub", and in order to reconstruct
  37.  * the "total" stub we have to create the union of them.
  38.  *
  39.  *===================================================================
  40.  */
  41.  
  42.  
  43. #include <stdio.h>
  44. #include "catalog/catname.h"
  45. #include "access/tupdesc.h"
  46. #include "access/ftup.h"
  47. #include "utils/log.h"
  48. #include "rules/prs2.h"
  49. #include "rules/prs2stub.h"
  50. #include "catalog/pg_proc.h"
  51. #include "catalog/pg_prs2stub.h"
  52. #include "utils/lsyscache.h"
  53. #include "utils/fmgr.h"
  54.  
  55.  
  56. static Prs2Stub prs2SlowlyGetRelationStub();
  57.  
  58. #ifdef OBSOLETE
  59. /*-------------------------------------------------------------------
  60.  * LOCAL STUFF...
  61.  */
  62. static void prs2ChangeRelationStub();
  63.  
  64. /*-------------------------------------------------------------------
  65.  *
  66.  * prs2AddRelationStub
  67.  *
  68.  * Add a new stub to the specified relation.
  69.  *
  70.  */
  71. void
  72. prs2AddRelationStub(relation, relstub)
  73. Relation relation;
  74. Prs2OneStub relstub;
  75. {
  76.     prs2ChangeRelationStub(relation, relstub, true);
  77. }
  78.  
  79. /*-------------------------------------------------------------------
  80.  *
  81.  * prs2DeleteRelationStub
  82.  *
  83.  * delete the given stub from the given relation
  84.  *-------------------------------------------------------------------
  85.  */
  86. void
  87. prs2DeleteRelationStub(relation, relstub)
  88. Relation relation;
  89. Prs2OneStub relstub;
  90. {
  91.     prs2ChangeRelationStub(relation, relstub, false);
  92. }
  93.  
  94.  
  95. /*-------------------------------------------------------------------
  96.  *
  97.  * prs2ChangeRelationStub
  98.  *
  99.  * This routine is called by both 'prs2AddRelationStub' and
  100.  * 'prs2DeleteRelationStub' and add/deletes  the given stub
  101.  * to/from the given relation
  102.  *
  103.  * if `addFlag' is true then we add a stub, otherwise we delete it.
  104.  *
  105.  *-------------------------------------------------------------------
  106.  */
  107.  
  108. static void
  109. prs2ChangeRelationStub(relation, relstub, addFlag)
  110. Relation relation;
  111. Prs2OneStub relstub;
  112. bool addFlag;
  113. {
  114.  
  115.     Relation prs2stubRelation;
  116.     HeapScanDesc scanDesc;
  117.     ScanKeyData scanKey;
  118.     HeapTuple tuple;
  119.     Buffer buffer;
  120.     HeapTuple newTuple;
  121.     Prs2Stub currentStubs;
  122.     bool newTupleFlag;
  123.     NameData relname; /* Added so we can pass Name_pg_prs2stub to
  124.                          RelationNameOpenHeapRelation */
  125.  
  126.     /*
  127.      * Add a stub record a a relation
  128.      * Go to the pg_prs2stub relation find the
  129.      * appropriate tuple, and add the specified lock to it.
  130.      */
  131.     strcpy(relname.data, Name_pg_prs2stub);
  132.  
  133.     prs2stubRelation = RelationNameOpenHeapRelation(&relname);
  134.  
  135.     ScanKeyEntryInitialize(&scanKey.data[0], 0, Anum_pg_prs2stub_prs2relid, 
  136.                            ObjectIdEqualRegProcedure,
  137.                            ObjectIdGetDatum(relation->rd_id));
  138.  
  139.     scanDesc = RelationBeginHeapScan(prs2stubRelation,
  140.                     0, NowTimeQual,
  141.                     1, &scanKey);
  142.     
  143.     tuple = HeapScanGetNextTuple(scanDesc, 0, &buffer);
  144.     if (HeapTupleIsValid(tuple)) {
  145.     newTupleFlag = false;
  146.     } else {
  147.     /*
  148.      * We didn't find a tuple in pg_prs2stub for
  149.      * this relation.
  150.      * Is this a `delete stub' operation?
  151.      * If yes complain!
  152.      * Otherwise create a brand new tuple...
  153.      */
  154.     if (!addFlag) {
  155.         elog(WARN, "DeleteRuleStub: Invalid rel OID %ld",relation->rd_id);
  156.     } else {
  157.         /*
  158.          * We must create a new tuple
  159.          * Initially its 'prs2stub' field will contain
  160.          * an empty rule stub.
  161.          */
  162.         Datum values[Natts_pg_prs2stub];
  163.         char nullarr[Natts_pg_prs2stub];
  164.         int i;
  165.         for (i=0; i<Natts_pg_prs2stub; i++)
  166.         nullarr[i] = 'n';
  167.         values[Anum_pg_prs2stub_prs2relid-1] = 
  168.             ObjectIdGetDatum(relation->rd_id);
  169.         nullarr[Anum_pg_prs2stub_prs2relid-1] = ' ';
  170.         values[Anum_pg_prs2stub_prs2stub-1] = 
  171.             StructPointerGetDatum(prs2StubToRawStub(prs2MakeStub()));
  172.         nullarr[Anum_pg_prs2stub_prs2stub-1] = ' ';
  173.         newTupleFlag = true;
  174.         tuple = FormHeapTuple(Natts_pg_prs2stub,
  175.                 RelationGetTupleDescriptor(prs2stubRelation),
  176.                 values,
  177.                 nullarr);
  178.     }
  179.     }
  180.  
  181.     /*
  182.      * We have found the appropriate tuple of the pg_prs2stub relation.
  183.      * Now find its old stubs...
  184.      */
  185.     currentStubs = prs2GetStubsFromPrs2StubTuple(tuple, buffer,
  186.                 RelationGetTupleDescriptor(prs2stubRelation));
  187.  
  188.     /*
  189.      * Now add/delete the given stub from the current stubs
  190.      */
  191.     if (addFlag) {
  192.     prs2AddOneStub(currentStubs, relstub);
  193.     } else {
  194.     prs2DeleteOneStub(currentStubs, relstub);
  195.     }
  196.  
  197.     /*
  198.      * Create a new tuple (a copy of the current tuple)
  199.      * in the pg_prs2stub relation
  200.      */
  201.     newTuple = prs2PutStubsInPrs2StubTuple(tuple, buffer,
  202.             RelationGetTupleDescriptor(prs2stubRelation),
  203.             currentStubs);
  204.     
  205. #ifdef STUB_DEBUG
  206.     if (STUB_DEBUG > 3) {
  207.     printf("prs2ChangeRelationStub (op=%s) NEW TUPLE=\n",
  208.         addFlag ? "add" : "delete");
  209.     debugtup(newTuple, RelationGetTupleDescriptor(prs2stubRelation));
  210.     }
  211. #endif STUB_DEBUG
  212.  
  213.     if (newTupleFlag) {
  214.     double dummy;
  215.     pfree(tuple);
  216.     RelationInsertHeapTuple(prs2stubRelation, newTuple, &dummy);
  217.     } else {
  218.     RelationReplaceHeapTuple(prs2stubRelation, &(tuple->t_ctid),
  219.                 newTuple, (double *)NULL);
  220.     }
  221.     
  222.     RelationCloseHeapRelation(prs2stubRelation);
  223.     HeapScanEnd(scanDesc);
  224.  
  225. }
  226. #endif
  227.  
  228. /*-------------------------------------------------------------------
  229.  *
  230.  * prs2DeleteRelationStub
  231.  *
  232.  * Delete the given stub from the given relation
  233.  *
  234.  */
  235. void
  236. prs2DeleteRelationStub(relation, relstub)
  237. Relation relation;
  238. Prs2OneStub relstub;
  239. {
  240.     ObjectId reloid;
  241.     Prs2Stub stubs;
  242.  
  243.     reloid = relation->rd_id;
  244.     stubs = prs2GetRelationStubs(reloid);
  245.     prs2DeleteOneStub(stubs, relstub);
  246.     prs2ReplaceRelationStub(reloid, stubs);
  247. }
  248.  
  249. /*-------------------------------------------------------------------
  250.  *
  251.  * prs2AddRelationStub
  252.  *
  253.  * Add a new stub to the specified relation.
  254.  *
  255.  */
  256. void
  257. prs2AddRelationStub(relation, relstub)
  258. Relation relation;
  259. Prs2OneStub relstub;
  260. {
  261.     ObjectId reloid;
  262.     Prs2Stub stubs;
  263.  
  264.     reloid = relation->rd_id;
  265.     stubs = prs2GetRelationStubs(reloid);
  266.     prs2AddOneStub(stubs, relstub);
  267.     prs2ReplaceRelationStub(reloid, stubs);
  268. }
  269.  
  270. /*-------------------------------------------------------------------
  271.  *
  272.  * prs2ReplaceRelationStub
  273.  *
  274.  * Replace the relation-level stubs of the given relation
  275.  * withe the given ones. The old ones are completely
  276.  * ignored.
  277.  *-------------------------------------------------------------------
  278.  */
  279.  
  280. void
  281. prs2ReplaceRelationStub(relationOid, newStubs)
  282. ObjectId relationOid;
  283. Prs2Stub newStubs;
  284. {
  285.  
  286.     Relation prs2stubRelation;
  287.     HeapScanDesc scanDesc;
  288.     ScanKeyData scanKey;
  289.     HeapTuple tuple;
  290.     Buffer buffer;
  291.     NameData relname;
  292.  
  293.     Prs2RawStub *pieces;
  294.     int npieces;
  295.     Datum values[Natts_pg_prs2stub];
  296.     char nullarr[Natts_pg_prs2stub];
  297.     int i,j;
  298.  
  299.  
  300.     /*
  301.      * First transform this stub in a raw stub (i.e. Prs2RwStub)
  302.      * and break it into small pieces, (so that each tuple is
  303.      * smaller than 8K.
  304.      */
  305.     pieces = prs2StubToSmallRawStubs(newStubs, 7000, &npieces);
  306.     
  307.     /*
  308.      * Go to the pg_prs2stub relation (i.e. pg_relation), and start
  309.      * scanning it for the appropriate tuples.
  310.      */
  311.     strcpy(relname.data, Name_pg_prs2stub);
  312.  
  313.     prs2stubRelation = RelationNameOpenHeapRelation(&relname);
  314.  
  315.     ScanKeyEntryInitialize(&scanKey.data[0], 0, Anum_pg_prs2stub_prs2relid,
  316.                            ObjectIdEqualRegProcedure,
  317.                            ObjectIdGetDatum(relationOid));
  318.  
  319.     scanDesc = RelationBeginHeapScan(prs2stubRelation,
  320.                     0, NowTimeQual,
  321.                     1, &scanKey);
  322.     
  323.     /*
  324.      * delete all the old tuples
  325.      */
  326.     do {
  327.     tuple = HeapScanGetNextTuple(scanDesc, 0, &buffer);
  328.     if (HeapTupleIsValid(tuple)) {
  329.         heap_delete(prs2stubRelation, &(tuple->t_ctid));
  330. #ifdef STUB_DEBUG
  331.         printf("prs2ReplaceRelationStub OLD TUPLE =\n");
  332.         debugtup(tuple,
  333.         RelationGetTupleDescriptor(prs2stubRelation));
  334. #endif STUB_DEBUG
  335.     }
  336.     } while (HeapTupleIsValid(tuple));
  337.  
  338.     /*
  339.      * and add thew new ones...
  340.      */
  341.     for (j=0; j<Natts_pg_prs2stub; j++)
  342.     nullarr[j] = 'n';
  343.     values[Anum_pg_prs2stub_prs2relid-1] = 
  344.         ObjectIdGetDatum(relationOid);
  345.     nullarr[Anum_pg_prs2stub_prs2relid-1] = ' ';
  346.     for (i=0; i<npieces; i++) {
  347.     /*
  348.      * create a new tuple
  349.      */
  350.     if (i==npieces-1)
  351.         values[Anum_pg_prs2stub_prs2islast-1] = CharGetDatum(true);
  352.     else
  353.         values[Anum_pg_prs2stub_prs2islast-1] = CharGetDatum(false);
  354.     nullarr[Anum_pg_prs2stub_prs2islast-1] = ' ';
  355.     values[Anum_pg_prs2stub_prs2no-1] = Int32GetDatum(i);
  356.     nullarr[Anum_pg_prs2stub_prs2no-1] = ' ';
  357.     values[Anum_pg_prs2stub_prs2stub-1] = 
  358.         StructPointerGetDatum(pieces[i]);
  359.     nullarr[Anum_pg_prs2stub_prs2stub-1] = ' ';
  360.     tuple = FormHeapTuple(Natts_pg_prs2stub,
  361.                 RelationGetTupleDescriptor(prs2stubRelation),
  362.                 values,
  363.                 nullarr);
  364.     /*
  365.      * append it to the relation
  366.      */
  367. #ifdef STUB_DEBUG
  368.     printf("prs2ReplaceRelationStub NEW TUPLE (%d out of %d) =\n",
  369.         i, npieces);
  370.     debugtup(tuple, RelationGetTupleDescriptor(prs2stubRelation));
  371. #endif STUB_DEBUG
  372.     heap_insert(prs2stubRelation, tuple, (double *)NULL);
  373.     }
  374.     RelationCloseHeapRelation(prs2stubRelation);
  375.     HeapScanEnd(scanDesc);
  376. }
  377.  
  378. /*======================================================================
  379.  *
  380.  * prs2GetRelationStubs
  381.  *
  382.  * given a relation OID, find all the associated rule stubs.
  383.  *
  384.  *======================================================================
  385.  */
  386. Prs2Stub
  387. prs2GetRelationStubs(relOid)
  388. ObjectId relOid;
  389. {
  390.  
  391.     Prs2RawStub temp, rawStubs;
  392.     Prs2RawStub rawStubsPiece;
  393.     Prs2Stub relstub;
  394.     int no;
  395.     bool islast;
  396.  
  397.     /*
  398.      * find the Prs2RawStub of the relation
  399.      * If there is no entry for this relation in pg_prs2stub
  400.      * then `get_relstubs' will return NULL
  401.      *
  402.      * NOTE: get_relstub creates a COPY of
  403.      * the raw relation stubs found in the tuple.
  404.      * so this memory should be freed when no longer needed.
  405.      */
  406.  
  407.     no = 0;
  408.     rawStubs = NULL;
  409.     do {
  410.     rawStubsPiece = get_relstub(relOid, no, &islast);
  411.     no++;
  412.     if (rawStubsPiece == NULL) {
  413.         islast = true;
  414.     } else {
  415.         /*
  416.          * we found s piece of the stub.
  417.          * "Append" it to the current stubs...
  418.          */
  419.         if (rawStubs == NULL) {
  420.         rawStubs = rawStubsPiece;
  421.         } else {
  422.         temp = prs2RawStubUnion(rawStubs, rawStubsPiece);
  423.         pfree(rawStubsPiece);
  424.         pfree(rawStubs);
  425.         rawStubs = temp;
  426.         }
  427.     }
  428.     } while (!islast);
  429.  
  430.     if (rawStubs==NULL) {
  431.     /*
  432.      * no stubs found for this relation
  433.      */
  434.     relstub = prs2MakeStub();
  435.     } else {
  436.     relstub = prs2RawStubToStub(rawStubs);
  437.     pfree(rawStubs);
  438.     }
  439.  
  440. #ifdef OUZODEBUG
  441.     {
  442.     Prs2Stub relstub2;
  443.     Name get_rel_name();
  444.     char *s1, *s2;
  445.  
  446.     relstub2 = prs2SlowlyGetRelationStub(relOid);
  447.     printf("--> Looking stubs for relation %ld (%s)\n",
  448.         relOid, get_rel_name(relOid));
  449.     s1 = prs2StubToString(relstub);
  450.     printf("--> syscache stub = %s\n", s1);
  451.     s2 = prs2StubToString(relstub2);
  452.     printf("--> relscan  stub = %s\n", s2);
  453.  
  454.     relstub = relstub2;
  455.     }
  456. #endif OUZODEBUG
  457.  
  458.     return(relstub);
  459. }
  460.  
  461. /*======================================================================
  462.  * prs2SlowlyGetRelationStub
  463.  *
  464.  * Get the stubs of a relation NOT by looking at the sys cache, 
  465.  * but by actually scanning the pg_prs2stub system catalog.
  466.  * Used for debugging (this stupid sys cache invalidation bug again,
  467.  * argh!!!!)
  468.  *======================================================================
  469.  */
  470. static
  471. Prs2Stub
  472. prs2SlowlyGetRelationStub(relationOid)
  473. ObjectId relationOid;
  474. {
  475.  
  476.     Relation prs2stubRelation;
  477.     HeapScanDesc scanDesc;
  478.     ScanKeyData scanKey;
  479.     HeapTuple tuple;
  480.     Buffer buffer;
  481.     HeapTuple newTuple;
  482.     Prs2Stub result;
  483.     Prs2RawStub temp, rawStub, rawStubPiece;
  484.     NameData relname;
  485.     Datum datum;
  486.     Boolean isNull;
  487.  
  488.     /*
  489.      * Go to the pg_prs2stub relation (i.e. pg_relation), find the
  490.      * appropriate tuple
  491.      */
  492.     strcpy(relname.data, Name_pg_prs2stub);
  493.  
  494.     prs2stubRelation = RelationNameOpenHeapRelation(&relname);
  495.  
  496.     ScanKeyEntryInitialize(&scanKey.data[0], 0, Anum_pg_prs2stub_prs2relid,
  497.                            ObjectIdEqualRegProcedure, 
  498.                            ObjectIdGetDatum(relationOid));
  499.  
  500.     scanDesc = RelationBeginHeapScan(prs2stubRelation,
  501.                     0, NowTimeQual,
  502.                     1, &scanKey);
  503.     
  504.     /*
  505.      * find all the tuples of pg_prs2stub for this relation.
  506.      */
  507.     rawStub = NULL;
  508.     do {
  509.     tuple = HeapScanGetNextTuple(scanDesc, 0, &buffer);
  510.     if (HeapTupleIsValid(tuple)) {
  511.         datum = HeapTupleGetAttributeValue(
  512.                 tuple,
  513.                 buffer,
  514.                 Anum_pg_prs2stub_prs2stub,
  515.                 RelationGetTupleDescriptor(prs2stubRelation),
  516.                 &isNull);
  517.         if (!isNull) {
  518.         rawStubPiece = (Prs2RawStub) DatumGetPointer(datum);
  519.         if (rawStub == NULL) {
  520.             rawStub = rawStubPiece;
  521.         } else {
  522.             temp = prs2RawStubUnion(rawStub, rawStubPiece);
  523.             pfree(rawStubPiece);
  524.             pfree(rawStub);
  525.             rawStub = temp;
  526.         }
  527.         }
  528.     }
  529.     } while (HeapTupleIsValid(tuple));
  530.  
  531.     if (rawStub == NULL) {
  532.     result = prs2MakeStub();
  533.     } else {
  534.     result = prs2RawStubToStub(rawStub);
  535.     pfree(rawStub);
  536.     }
  537.  
  538.     RelationCloseHeapRelation(prs2stubRelation);
  539.     HeapScanEnd(scanDesc);
  540.  
  541.     return(result);
  542.  
  543. }
  544.  
  545. #ifdef OBSOLETE
  546. /*======================================================================
  547.  *
  548.  * prs2GetStubsFromPrs2StubTuple
  549.  *
  550.  * given a tuple form the pg_prs2stub relation, return
  551.  * the rule stubs stored in this tuple
  552.  *======================================================================
  553.  */
  554. Prs2Stub
  555. prs2GetStubsFromPrs2StubTuple(tuple, buffer, tupleDescriptor)
  556. HeapTuple tuple;
  557. Buffer buffer;
  558. TupleDescriptor tupleDescriptor;
  559. {
  560.     Datum datum;
  561.     Boolean isNull;
  562.     Prs2RawStub rawStub;
  563.     Prs2Stub relstub;
  564.  
  565.     /*
  566.      * extract the `Prs2RawStub' from the tuple
  567.      * and then transform it to a `Prs2Stub'
  568.      */
  569.     datum = HeapTupleGetAttributeValue(
  570.                 tuple,
  571.                 buffer,
  572.                 Anum_pg_prs2stub_prs2stub,
  573.                 tupleDescriptor,
  574.                 &isNull);
  575.  
  576.     if (isNull) {
  577.     /*
  578.      * create an empty stub
  579.      */
  580.     relstub = prs2MakeStub();
  581.     return(relstub);
  582.     } else {
  583.     rawStub = (Prs2RawStub) DatumGetPointer(datum);
  584.     relstub = prs2RawStubToStub(rawStub);
  585.     return(relstub);
  586.     }
  587. }
  588.  
  589. /*======================================================================
  590.  *
  591.  * prs2PutStubsInPrs2StubTuple
  592.  *
  593.  * Store the given stubs to a pg_prs2stub relation tuple
  594.  * return the new tuple
  595.  *
  596.  *======================================================================
  597.  */
  598. HeapTuple
  599. prs2PutStubsInPrs2StubTuple(tuple, buffer, tupleDescriptor, relstubs)
  600. HeapTuple tuple;
  601. Buffer buffer;
  602. TupleDescriptor tupleDescriptor;
  603. Prs2Stub relstubs;
  604. {
  605.     Datum values[Natts_pg_prs2stub];
  606.     char nullarr[Natts_pg_prs2stub];
  607.     int i;
  608.     HeapTuple newTuple;
  609.     Datum datum;
  610.     Boolean isNull;
  611.     Prs2RawStub rawStub;
  612.  
  613.     /*
  614.      * extract the values of the old tuple
  615.      */
  616.     for (i=0; i<Natts_pg_prs2stub; i++) {
  617.     values[i] = HeapTupleGetAttributeValue(
  618.                 tuple,
  619.                 buffer,
  620.                 i+1,
  621.                 tupleDescriptor,
  622.                 &isNull);
  623.     nullarr[i] = isNull ? 'n' : ' ';
  624.     }
  625.  
  626.     /*
  627.      * change the value of the 'stub' attribute of the tuple
  628.      */
  629.     rawStub = prs2StubToRawStub(relstubs);
  630.     datum = PointerGetDatum(rawStub);
  631.     values[Anum_pg_prs2stub_prs2stub-1] = datum;
  632.     nullarr[Anum_pg_prs2stub_prs2stub-1] = ' ';
  633.  
  634.     /*
  635.      * Now form the new tuple
  636.      */
  637.     newTuple = FormHeapTuple(
  638.             Natts_pg_prs2stub,
  639.             tupleDescriptor,
  640.             values,
  641.             nullarr);
  642.  
  643.     pfree(rawStub);
  644.     return(newTuple);
  645.  
  646. }
  647. #endif OBSOLETE
  648.